﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Bing.Toolkit.Utility
{
    /// <summary>
    /// /* 4位          十进制:15                   十六进制:F                  二进制:1111               
    ///  * 八位         十进制:255                  十六进制:FF                 二进制:11111111          
    ///  * 十六位       十进制:65535                十六进制:FFFF               二进制:1111111111111111 
    ///  * 三十二位     十进制:4294967295           十六进制:FFFFFFFF           二进制:11111111111111111111111111111111
    ///  * 六十四位     十进制:18446744073709551615 十六进制:FFFFFFFFFFFFFFFF   二进制:1111111111111111111111111111111111111111111111111111111111111111
    ///  */
    /// </summary>
    public class Bitwise
    {
        public struct Defualt
        {
            public const Int32 VeryLow = 15;
            public const Int32 Low = 255;
            public const Int32 Norm = 65535;
            public const Int64 High = 4294967295;
            public const UInt64 VeryHigh = 18446744073709551615;
        }

        /// <summary>
        /// 获取当前位置状态
        /// </summary>
        /// <param name="val">要校验的值</param>
        /// <param name="index">要查找的位置,范围1-64之间</param>
        /// <returns></returns>
        public static bool GetLocation(UInt64 val, int index)
        {
            if (index < 1 || index > 64)
                throw new Exception("请输入1-64之间的整数！");

            return Convert.ToBoolean((val >> (index - 1)) & 0x0001);
        }

        /// <summary>
        /// 设置当前位置装态
        /// </summary>
        /// <param name="val">要设置的值</param>
        /// <param name="index">要查找的位置,范围1-64之间</param>
        /// <param name="ival">位置状态</param>
        /// <returns></returns>
        public static UInt64 SetLocation(UInt64 val, int index, bool ival)
        {
            if (index < 1 || index > 64)
                throw new Exception("请输入1-64之间的整数！");

            byte b = Convert.ToByte(ival);
            UInt64 tmp = val >> (index - 1);

            if ((tmp & 0x0001) == b)
            {
                return val;
            }
            else
            {
                if (ival)
                {
                    return val | Convert.ToUInt64(ival) << (index - 1);
                }
                return val & ((UInt64)(0x00000001 << (index - 1)) ^ 0xFFFFFFFFFFFFFFFF);
            }
        }

        /// <summary>
        /// 获取所有位都是1或0的数字
        /// </summary>
        /// <param name="ival">位置状态</param>
        /// <returns></returns>
        public static UInt64 GetDefaultLocation(bool ival)
        {
            return Convert.ToUInt64(new string(ival ? '1' : '0', 64), 2);
        }

        /// <summary>
        /// 获取一个位置数组
        /// </summary>
        /// <param name="val"></param>
        /// <returns></returns>
        public static List<bool> GetLocationArray(UInt64 val)
        {
            char[] tmp = val.ToString().ToCharArray();
            List<bool> result = new List<bool>();

            foreach (char n in tmp)
            {
                result.Add(Convert.ToBoolean(n));
            }

            return result;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="val"></param>
        /// <param name="indexs"></param>
        /// <param name="ival"></param>
        /// <returns></returns>
        public static UInt64 SetLocationArray(UInt64 val, List<int> indexs, bool ival)
        {
            UInt64 tmp = 0;

            foreach (int n in indexs)
            {
                tmp = SetLocation(val, n, ival);
            }

            return tmp;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="val"></param>
        /// <param name="indexs"></param>
        /// <param name="ivals"></param>
        /// <returns></returns>
        public static UInt64 SetLocationArray(UInt64 val, int[] indexs, bool[] ivals)
        {
            UInt64 tmp = 0;

            if (indexs.Length != ivals.Length)
                throw new Exception("索引与相对应的值长度不一样！");
            int len = indexs.Length;

            for (int i = 0; i < len; i++)
            {
                tmp = SetLocation(val, indexs[i], ivals[i]);
            }

            return tmp;
        }

        /// <summary>
        /// 64位无符号整型转换为二进制
        /// </summary>
        /// <param name="val"></param>
        /// <returns></returns>
        public static String UInt64ToString(UInt64 val)
        {
            if (val < 2) return val.ToString();

            StringBuilder result = new StringBuilder();

            do
            {
                result.Insert(0, val % 2);
            } while ((val = (val / 2)) != 0);

            return result.ToString();
        }
    }
}
